﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Administration.Backup;
using Microsoft.SharePoint.Administration.Health;

namespace SPHealth.SharePoint.HealthRules.SP.Rules.Availability
{
    class WarnFarmBackupHistory : SPHealthAnalysisRule
    {
        #region Locals
        private const string MaxDaysBackup = "MaxDaysBackup";
        private const string ruleTitle = "WarnFarmBackupHistory";
        private DateTime lastFarmBackup = DateTime.MinValue;
        #endregion

        #region Constructor
        /* This rules does not require a constructor */
        #endregion

        #region Fields

        // the category to display this rule under
        public override SPHealthCategory Category
        {
            get { return SPHealthCategory.Availability; }
        }

        // the type or error to flag this rule as
        public override SPHealthCheckErrorLevel ErrorLevel
        {
            get { return SPHealthCheckErrorLevel.Warning; }
        }

        // the Explanation for the rule and what is not working
        public override string Explanation
        {
            get { return string.Format("This farm does not appear to have been backed up within the past {0} days. The most recent farm backup that can be found was completed at {1}", common.GetRuleSetting(MaxDaysBackup, ruleTitle), lastFarmBackup.ToString()); }
        }

        // how to fix the issue
        public override string Remedy
        {
            get { return "Ensure that regular SharePoint farm backups are taken. See Plan for backup and recovery (SharePoint 2010) - http://technet.microsoft.com/en-gb/library/cc261687.aspx"; }
        }

        // the Summary for the rule
        public override string Summary
        {
            get { return "The farm has not been backed up recently."; }
        }

        public override SPHealthAnalysisRuleAutomaticExecutionParameters AutomaticExecutionParameters
        {
            get
            {
                SPHealthAnalysisRuleAutomaticExecutionParameters retval = new SPHealthAnalysisRuleAutomaticExecutionParameters();
                retval.Schedule = SPHealthCheckSchedule.Daily;
                retval.Scope = SPHealthCheckScope.Any;
                retval.ServiceType = typeof(SPTimerService);
                return retval;
            }
        }
        #endregion

        #region Methods

        // used to provide the configuration list item title
        public static string GetTitle()
        {
            // return the title for the rule
            return ruleTitle;
        }

        // used to provide the default configuration settings
        public static IDictionary<string, string> GetDefaultSettings()
        {
            // return the default settings for the rule
            IDictionary<string, string> settings = new Dictionary<string, string>();
            settings.Add("Comment1", "Enter the maximum number of days that can elapse before a warning");
            settings.Add("Comment2", "is raised to indicate that a farm backup is required.");
            settings.Add(MaxDaysBackup, "7");
            return settings;
        }

        // this method is called whenever the rule is executed
        public override SPHealthCheckStatus Check()
        {
            if (!SPFarm.Joined)
            {
                throw new InvalidOperationException();
            }

            SPBackupRestoreConfigurationSettings backupSettings = SPBackupRestoreConfigurationSettings.CreateSettings(SPFarm.Local);

            // the check below will only be performed if backups have been taken
            // if backups have never been taken this will be picked up by the WarnFarmBackup rule
            if (!string.IsNullOrEmpty(backupSettings.PreviousBackupLocation))
            {

                //set up
                lastFarmBackup = DateTime.MinValue;

                // get out list of previous backups
                SPBackupRestoreHistoryList historyList = null;
                historyList = SPBackupRestoreConsole.GetHistory(backupSettings.PreviousBackupLocation, true);

                // check the backup history for valid farm backups
                for (int x = 0; x < historyList.Count; x++)
                {
                    SPBackupRestoreHistoryObject historyObject = historyList[x];
                    // if the item a backup
                    if (historyObject.IsBackup)
                    {
                        // is it s full backup
                        if (historyObject.BackupMethod == SPBackupMethodType.Full)
                        {
                            // is it a farm backup
                            if (historyObject.TopComponent == "Farm")
                            {
                                // is it for the current farm?
                                if (historyObject.TopComponentId == SPFarm.Local.Id)
                                {
                                    // did the backup work
                                    if (!historyObject.IsFailure)
                                    {
                                        // we've got a candidate for our list of backups
                                        if (historyObject.EndTime > lastFarmBackup)
                                            lastFarmBackup = historyObject.EndTime;
                                    }
                                }
                            }
                        }
                    }
                }

                // determine if the last backup date is within our threshold
                if (lastFarmBackup == DateTime.MaxValue ||
                    DateTime.Now.Subtract(lastFarmBackup).TotalDays > Convert.ToInt32(common.GetRuleSetting(MaxDaysBackup, ruleTitle)))
                {
                    // fail the rule as the backups are too old
                    return SPHealthCheckStatus.Failed;
                }
            }

            return SPHealthCheckStatus.Passed;
        }

        #endregion

    }
}
